Back to Main Menu

Create Assessment Form from csv (Assetic Python SDK)

Introduction

The Assetic Python SDK allows a new Assessment form to be created using a csv file to define the form.

 

There are 2 aspects to the form creation:

  1. Defining the fields in the form via a csv file.

  2. Setting basic form attributes such as form name, description, form level etc. This step has been simplified by a script that prompts you for the required information. See the Quick Start below.

 

Refer also to the article Manage Custom Assessment Forms for additional information about assessment forms and how they are created using the Assetic application itself.

Quick Start

Note: Make sure your Assetic Python SDK version is 2017.13.1.0 or greater.  Refer to the article Assetic Python SDK Quick Start for details on how to install or upgrade the Assetic Python SDK.

First create a csv file (using Excel or other editor) or Download this sample here: (FormFields.csv)

 

Contains parent/child comboxbox (FormFieldsParentChild.csv)

 

(Samples may open in the browser rather than downloading.  Right-click in the browser and choose the 'Save As' option)

 

Data Sample:

The following csv data sample shows a typical structure for creating an assessment form.  It is shown in a grid to make each column more obvious.

 

The column structure of this csv data is Label, Type, Attributes, Widget, Required, Hint

Operating Facility   100 Facility Detail True The facility name
Primary Location   100 Facility Detail True Main Location
System Dropdown 1|Type A;2|Type B System Detail True  
Classification     System Detail    
Installed Area NumericStepper 0|100|1|n0 System Detail    
Complexity of Access Dropdown Low|Low;Medium|Medium;High|High Facility Detail    
Comment MultiLineText 1000 System Detail   As per standard AC:3423
Is Active Checkbox   Facility Detail    
Tagged Service Date Date   System Detail    
Running Since DateTime   System Detail   The date and time the unit was last started
Location Map   Facility Detail    

 

Some notes about the above sample:

  • Only 1 column is mandatory, the "Label" column. All other columns are optional, and the order of the columns is not fixed.

  • 'Facility Detail' and 'System Detail' are the labels for the 2 control groups that will contain the form fields. The form will therefore need to be created with a layout containing at least 2 control groups

  • Where the form field "Type" column is empty, the default will be TextBox.

  • Default values are applied if the "Attributes" cell is empty

  • The format of the contents of the "Attributes" cell varies depending on the form field type

  • The default value for 'Required' is False (i.e. the field is not mandatory)

Form Creation

Having created the csv file, the next step is to create the form.

Hint: You may need to right click and 'Save As' (Assetic.AssessmentFormCreateByPrompt.py)

 

This script will prompt you for the form details and create the form. Once the form is created you will be prompted to launch Assetic. Assetic will launch and display the new form in the Assessments Admin module.

 

Defining Parent-Child Combobox Relationships

A parent-child combobox relationship can be defined such that the selection of a value in the parent combobox results in the filtering of child combobox values.

 

To define these relationships 2 additional columns are added to the csv file. The columns are only populated for the child combobox definition row in the the csv:

  • ParentLabel

    • The 'label' of the parent combox to associate the child combobx to

  • ParentRelation

    • This is the relationship of the child combobox values to the parent comboxbox values and is by its nature complex to define.

    • The definition requires each child combobox value to be linked to values from the parent combobox.

      • A pair of carets ^^ to delimit each child combobox link setting

      • Within each child combobox link setting the parent combobox values are delimited by a semicolon. A pipe is used to delimit the child combobox value from the subsequent list of parent combobox values

 

The following example from the sample file FormFieldsParentChild.csv illustrates the configuration.

 

Label Type Attributes ParentRelation ParentLabel
System Dropdown 1|Type A;2|Type B;3|All    
Sub System Dropdown 1|Sub A1;2|Sub A2;3|Sub B1;4|Sub B2 1|1;3^^2|1;3^^3|2;3^^4|2;3 System

 

Based on the above configuration the following outcome is expected:

Parent Selection Child Selection Options
Type A Sub A1, Sub A2
Type B Sub B1, Sub B2
All Sub A1, Sub A2, Sub B1, Sub B2

 

Advanced Options and Field Descriptions

The Assetic Python SDK supports form creation without having to use the script AssessmentFormCreateByPrompt.py. The following sections describe in detail the structure of the field types and how to create a form without using the script from the Quick Start section above.

1. Form Attributes

The python object assetic.AssessmentFormCreateRepresentation is used to define the form attributes required by the Assessments API.

 

The following attributes of an assessment form can be set via this representation:

Attribute

Name

Description Mandatory Default
form_name The name of the form to create.  Must be unique.  This will not be user visible, but this is the reference name used when using the Assetic Data Exchange API for bulk importing Assessment Form Results (Data Exchange Integration) Yes -
form_label  A user friendly label for the form that is shown when selecting the form in Data Exchange and advanced search Yes -
form_level Defines the module that the from targets.  One of: "Asset", "GroupAsset", "ComplexAsset","Component", "ComponentServiceCriteria","NetworkEntity","SimpleAsset", "WorkOrder", "WorkRequest", "WorkTask","AssesmentsResult", "Documents", "AsmtProject", "AsmtTask", "ServiceCriteria" Yes -
version A version number to assign to the form No 1
can_add_attachment Allows document attachments to be linked to the form.  Boolean True/False No True
tab_label The label of the tab in the form  No "Tab"
layout_pattern  Defines the pattern of the form layout.  Options include but not limited to: "Single", "column: 2 equal columns" No  "Single"
widget_labels

For the given layout, each group of controls has a label.  This is an array.

"Single" has 1 group of controls, "column: 2 equal columns" has 2 groups of controls so 2 labels are required

No "Data"
label_formatter Use a custom method to reformat the label as it appears in the csv file.  Examples include replacing "_" with " ", or converting upper case to 'proper case' so that the labels are more user friendly.  Useful where an external application is generating the csv file. No -

 

2. Form Labels - CSV file structure

A csv file is used to define the list of fields in a form.

NOTE  this file should not have a 'header' row that defines each column. The column structure is defined when executing the form creation.

 

The structure of the csv file follows a basic pattern whereby each row in the csv file represents a control in the form. A "control" is the fields in a form that data will be added to.

 

At a minimum the 'label' (user-visible label) of the control is required. The control type will default to 'TextBox' if only a list of labels is provided.

 

The controls available are:

Type Description Data Attributes Default Data  Settings
TextBox Standard single line text box Character limit 200 character limit
MultiLineText Text that may span multiple lines.  Use where there is a large amount of text Character limit 1000 character limit
Dropdown A dropdown list of items.  Can set values with user friendly descriptions Dropdown items, values with corresponding labels -
Date A datetime field that allows date to be selected by a calendar popup - -
DateTime A datetime field that allows date to be selected by a calendar popup and time to be selected by a time dropdown - -
NumericStepper

A numeric field with arrows to increase or decrease the number. The minimum value, maximum value, and value to increment the number by via the stepper may also be defined 

Minimum value, Maximum value, Step value, number format

min=0, max=100, step=1, format=n0

CheckBox A True/False style tick box - -
Map A map window - -

 

A column in the csv file that uses the same control type names as above can be used to set the control type for each label. It is permissible to use control names that vary from the above - refer to 'Non-standard control type names' below.

 

The following attributes for a control may be defined:

Attribute Type Description Format Default
Attributes The data attributes of the control as defined in the table above per control type.  This is a single column in the csv file that used for all the different control types.  The format will therefore change per control type.

For Dropdown separate the value from the label with "|", and separate each pair of items with ";".  Optionally use a separate column for dropdown items (format is unchanged)

For Numeric stepper separate min value, max value, step increment, and number format with "|".  Optionally use up to 4 separate columns in the file purely for stepper attributes ('minval", "maxval", "increment", "valueformat")  

For text and multiline text  define an integer value for field length.  Optionally use a separate column in the file purely for 'Length'

As above

Hint A 'mouse-over' hint (tooltip) to apply to the control. Text  No hint if undefined
Required Indicates the field is mandatory, and when viewing the form an asterisk will appear beside the label True/False False
Name The reference name for the control.  Use this if integrating to another system and the name is required for integration Text.  Cannot start with a number and should not have hyphens within the name.  Must be unique within the form A unique id will be generated for the name 
 Widget  The name of the form group widget to place the control in.  Required if a layout with more than one form group widget has been defined. Text.  Must match the name of one of the widgets from the form definition "widget_labels" -

 

3. Non-standard control type names

If another system has created the csv file, and the control type names vary from the above list, the control type name used in the csv file can be matched to one of the examples above using the "control_types" dictionary property of the SDK AssessmentHelper module.

assesshelp = assetic.AssessmentHelper(asseticsdk.client)     assesshelp.control_types["MultiLineText"] = "Multi line Text" assesshelp.control_types["NumericStepper"] = "Numeric"

Code Sample

The following code sample is a complete sample for creating an assessment form from a csv file.  It uses the same csv data as in the sample above, except the names for the types "MultiLineText" and "NumericStepper" are different in the csv file (to illustrate how this is managed)

  1. """
  2. Example script to create an assessment form
  3. (Assetic.AssessmentFormCreate.py)
  4. Creates an assessment form in Assetic
  5. """
  6. import assetic
  7. from assetic import Configuration
  8. from assetic import ApiClient
  9. from assetic import AssessmentTools
  10. import re #to replace camelcase with spaced label
  11. import csv #to read csv file with form definition
  12. import six
  13. # Assetic SDK instance.
  14. asseticsdk = assetic.AsseticSDK("c:/users/you/assetic.ini",None,"Info")
  15. def main():
  16. fid=67
  17. assesshelp = AssessmentHelper(asseticsdk.client)
  18. form_repr = AssessmentFormCreateRepresentation()
  19. form_repr.form_name = "ALPACA{0}".format(fid)
  20. form_repr.form_label = "Alpaca Test Form {0}".format(fid)
  21. form_repr.form_level = "Asset"
  22. form_repr.version = 1
  23. form_repr.can_add_attachment = True
  24. form_repr.tab_label = "Data Tab"
  25. form_repr.layout_pattern = "Single"
  26. form_repr.layout_pattern = "column: 2 equal columns"
  27. widget_labels = list()
  28. widget_labels.append("Section 1")
  29. widget_labels.append("Section 2")
  30. form_repr.widget_labels = widget_labels
  31. form_repr.label_formatter = None
  32. assesshelp.control_types["MultiLineText"] = "Multi line Text"
  33. assesshelp.control_types["NumericStepper"] = "Numeric"
  34. csv_structure = None
  35. csvfile = "C:/temp/HVAC fields.csv"
  36. assesshelp.create_form_from_csv(form_repr,csvfile,csv_structure)
  37. class AssessmentHelper(object):
  38. """
  39. Class to manage simplified processes for creating assessment forms
  40. such
  41. Uses the AssessmentTools class
  42. """
  43. def __init__(self, api_client=None):
  44. config = Configuration()
  45. if api_client:
  46. self.api_client = api_client
  47. else:
  48. if not config.api_client:
  49. config.api_client = ApiClient()
  50. self.api_client = config.api_client
  51. self.logger = config.packagelogger
  52. self.assesstool = assetic.AssessmentTools()
  53. self._control_types = self.initiate_control_types()
  54. @property
  55. def control_types(self):
  56. """
  57. dictionary of control type. The dictionary values can be changed
  58. to match the source data. The corresponding keys are tested for when
  59. determine which control to create
  60. """
  61. return self._control_types
  62. @control_types.setter
  63. def control_types(self,control_types):
  64. self._control_types = control_types
  65. def create_form_from_csv(self,form_repr,csvfile,structure=None):
  66. """
  67. create an assessment form from a csv file definition
  68. :param form_repr: A representation containing the core form
  69. creation details. AssessmentFormCreateRepresentation
  70. :param csvfile: The file containing the form definition
  71. :param structure: an optional mapping of row number in csv file to
  72. form creation purpose. e.g row 1 = control header, row 2 = control type
  73. :returns: >0=error, 0 = Success
  74. """
  75. form_name = form_repr.form_name
  76. if form_repr.form_label == None:
  77. form_label = form_repr.form_name
  78. else:
  79. form_label = form_repr.form_label
  80. form_level = form_repr.form_level
  81. version = form_repr.version
  82. can_add_attachment = form_repr.can_add_attachment
  83. tab_label = form_repr.tab_label
  84. layout_pattern = form_repr.layout_pattern
  85. widget_labels = form_repr.widget_labels
  86. ##first create the form definition
  87. form = self.assesstool.new_form(form_name,form_level,form_label)
  88. ##create tab and widgets
  89. tab = self.assesstool.add_tab_with_widgets_to_form(form,tab_label,
  90. widget_labels,layout_pattern)
  91. if tab == None:
  92. ##error encountered
  93. return 1
  94. ##get the structure from csv
  95. rows = self.read_csv_file_into_dict(csvfile,structure)
  96. if len(rows) == 1:
  97. return 1
  98. ##Add the controls
  99. for row in rows:
  100. self.process_csv_dict_row(row,tab,widget_labels)
  101. ##now create form
  102. self.assesstool.create_form(form)
  103. def read_csv_file_into_dict(self,filename,structure=None):
  104. """
  105. Read the the contents of a csv file into a representation that can be
  106. used to build the controls on a form
  107. :param filename: the file to read
  108. :param structure: the layout mapping of the rows in the file
  109. :returns: a list of the representation
  110. Assetic3IntegrationRepresentationsAssessmentFormFormControlRepresentation()
  111. """
  112. if structure == None:
  113. structure = ("Label","Type","Attributes","Widget","Required")
  114. rows = list()
  115. if six.PY2:
  116. with open(filename, 'rt') as csvfile:
  117. readCSV = csv.DictReader(
  118. csvfile,fieldnames=structure,delimiter=',')
  119. for row in readCSV:
  120. rows.append(row)
  121. else:
  122. with open(filename, 'rt', encoding='utf-8', newline = '') as csvfile:
  123. readCSV = csv.DictReader(csvfile,fieldnames=structure,
  124. delimiter=',')
  125. for row in readCSV:
  126. rows.append(row)
  127. return rows
  128. def process_csv_dict_row(self,field_def,tab,widget_labels):
  129. """
  130. The field definition is from csv.DictReader.
  131. Look for specific headers to determine
  132. what kind of control to create and it's attributes.
  133. :param field_def: the dictionary for a field
  134. :param tab: the tab to add the control to
  135. :param widget_labels: the widget to add the control to
  136. must be in the tab
  137. :returns: a list of the representation
  138. Assetic3IntegrationRepresentationsAssessmentFormFormControlRepresentation()
  139. """
  140. label = None
  141. if "Label" in field_def:
  142. label = field_def["Label"]
  143. else:
  144. #assume first element is the label
  145. label = field_def[0]
  146. #check if hint for control but otherwise leave null
  147. hint = None
  148. if "Hint" in field_def:
  149. hint = field_def["Hint"]
  150. #check if name for control but otherwise leave null
  151. name = None
  152. if "Name" in field_def:
  153. name = field_def["Name"]
  154. #check if 'required' is set
  155. required = None
  156. if "Required" in field_def:
  157. required = field_def["Required"]
  158. #check if widget is defined. If not set as first label
  159. widget_label = widget_labels[0]
  160. if "Widget" in field_def and field_def["Widget"] in widget_labels:
  161. widget_label = field_def["Widget"]
  162. ##now test for type and create control
  163. if "Type" not in field_def:
  164. #assume text box
  165. field_def["Type"] = "textbox"
  166. if "Type" in field_def:
  167. if field_def["Type"].lower() == \
  168. self._control_types["TextBox"].lower():
  169. #Standard text box
  170. #get length
  171. length = 200 #Default field length(will be used if undefined)
  172. if "Length" in field_def:
  173. length = self.get_numeric_or_default(
  174. field_def["Length"],200)
  175. elif "Attributes" in field_def:
  176. length = self.get_numeric_or_default(
  177. field_def["Attributes"],200)
  178. control = self.assesstool.new_text_control(label,name,length,
  179. hint=hint,required=required)
  180. elif field_def["Type"].lower() == \
  181. self._control_types["MultiLineText"].lower():
  182. ##this is a multiline text box
  183. length = 1000 #Default field length(will be used if undefined)
  184. if "Length" in field_def:
  185. length = self.get_numeric_or_default(
  186. field_def["Length"],1000)
  187. elif "Attributes" in field_def:
  188. length = self.get_numeric_or_default(
  189. field_def["Attributes"],1000)
  190. control = self.assesstool.new_multiline_text_control(label,
  191. name,length,hint=hint,required=required)
  192. elif field_def["Type"].lower() == \
  193. self._control_types["Dropdown"].lower():
  194. ##this is a combobox (drop down list)
  195. #get items
  196. itemstring = None
  197. if "DropdownItems" in field_def:
  198. itemstring = field_def["DropdownItems"]
  199. elif "Attributes" in field_def:
  200. itemstring = field_def["Attributes"]
  201. item_delim=";" #hardcode delimiter for the moment
  202. key_value_delim="|" #hardcode delimiter for the moment
  203. items = self.get_combobox_items(
  204. itemstring,item_delim,key_value_delim)
  205. control = self.assesstool.new_combobox_control(label,name,
  206. items=items,hint=hint,required=required)
  207. elif field_def["Type"].lower() == \
  208. self._control_types["Date"].lower():
  209. ##this is a date picker
  210. control = self.assesstool.new_date_control(label,name,
  211. hint=hint,required=required)
  212. elif field_def["Type"].lower() == \
  213. self._control_types["DateTime"].lower():
  214. ##this is a date picker
  215. control = self.assesstool.new_datetime_control(label,name,
  216. hint=hint,required=required)
  217. elif field_def["Type"].lower() == \
  218. self._control_types["NumericStepper"].\
  219. lower():
  220. ##this is a numeric stepper
  221. #get items
  222. sdef = self.get_stepper_defs(field_def)
  223. control = self.assesstool.new_stepper_control(label,name,
  224. sdef["minval"],sdef["maxval"],sdef["increment"],
  225. mask=sdef["valueformat"],hint=hint,required=required)
  226. elif field_def["Type"].lower() == \
  227. self._control_types["CheckBox"].lower():
  228. ##this is a checkbox
  229. control = self.assesstool.new_checkbox_control(label,name,
  230. hint=hint,required=required)
  231. elif field_def["Type"].lower() == \
  232. self._control_types["Map"].lower():
  233. ##this is a map control
  234. control = self.assesstool.new_map_control(label,name,
  235. hint=hint,required=required)
  236. else:
  237. ##Assume text
  238. #get length
  239. length = 200 #Default field length(will be used if undefined)
  240. if "Length" in field_def:
  241. length = self.get_numeric_or_default(
  242. field_def["Length"],200)
  243. elif "Attributes" in field_def:
  244. length = self.get_numeric_or_default(
  245. field_def["Attributes"],200)
  246. control = self.assesstool.new_text_control(label,name,length,
  247. hint=hint,required=required)
  248. #Add the control definition to the tab
  249. if control != None:
  250. self.assesstool.add_control_to_tab_widget(tab,widget_label,
  251. control)
  252. def get_combobox_items(self,itemstring,item_delim=";",key_value_delim="|"):
  253. """
  254. given a string decode into a list of key/value pairs and create
  255. combobox items.
  256. By default key/value pairs are separated by ";"
  257. By default "|" for splitting key from value
  258. If only value supplied then key = value
  259. :param itemstring: the string containing key/value pairs
  260. :param item_delim: delimiter between each set of items (key/value pairs)
  261. Default = ";"
  262. :param key_value_delim:delimiter between key and value. default = "|"
  263. :returns: a list of combobox item representations
  264. Assetic3IntegrationRepresentationsAssessmentFormFormControlRepresentation
  265. """
  266. items = list()
  267. if itemstring == None or itemstring.strip() == "":
  268. #no lookups items defined
  269. return items
  270. #split into key/value pairs
  271. pairs = itemstring.split(item_delim)
  272. for kvp in pairs:
  273. #split key and value
  274. itemkvp = kvp.split(key_value_delim)
  275. if len(itemkvp) == 1:
  276. #only label defined. Set key to label
  277. itemkvp = itemkvp + itemvkp
  278. #add item representation to items list
  279. items.append(self.assesstool.new_combobox_item(
  280. itemkvp[1],itemkvp[0]))
  281. return items
  282. def get_stepper_defs(self,field_def):
  283. """
  284. given a form field configuration definition, test if there are settings
  285. for a numeric stepper
  286. :param field_def: the dictionary of settings to test
  287. :returns: a dictionary of the parameters and their value
  288. """
  289. attributes_delim="|" #hardcode attributes delimiter for the moment
  290. default_min = 0
  291. default_max = 0
  292. default_inc = 0
  293. default_format = "n0"
  294. stepperdict = dict()
  295. ##apply defaults and then override if there is a setting
  296. stepperdict["minval"] = default_min
  297. stepperdict["maxval"] = default_max
  298. stepperdict["increment"] = default_inc
  299. stepperdict["valueformat"] = default_format
  300. #First look for separately defined parameters
  301. useatts = True #flag to indicate use of generic attributes field
  302. if "MinValue" in field_def:
  303. stepperdict["minval"] = field_def["MinValue"]
  304. useatts = False
  305. if "MaxValue" in field_def:
  306. stepperdict["maxval"] = field_def["MaxValue"]
  307. useatts = False
  308. if "ValueIncrement" in field_def:
  309. stepperdict["increment"] = field_def["ValueIncrement"]
  310. useatts = False
  311. if "ValueFormat" in field_def:
  312. stepperdict["valueformat"] = field_def["ValueFormat"]
  313. #If useatts = True set then look for delimited 'Attributes' and split
  314. if useatts == True and "Attributes" in field_def and \
  315. field_def["Attributes"] != None:
  316. stepperdefs = field_def["Attributes"].split(attributes_delim)
  317. stepperdict["minval"] = self. get_numeric_or_default(
  318. stepperdefs[0],default_min)
  319. if len(stepperdefs) > 1:
  320. stepperdict["maxval"] = self.get_numeric_or_default(
  321. stepperdefs[1],1000)
  322. if len(stepperdefs) > 2:
  323. stepperdict["increment"] = self.get_numeric_or_default(
  324. stepperdefs[2],1)
  325. if len(stepperdefs) > 3:
  326. stepperdict["valueformat"] = stepperdefs[3]
  327. return stepperdict
  328. def get_numeric_or_default(self,value,default):
  329. """
  330. given a string, test if numeric and if not return default
  331. :param value: the string to test
  332. :param default: the default vaue.Must be a numeric (is not validated)
  333. :returns: the reformatted value as a numeric
  334. """
  335. try:
  336. numeric = value/1
  337. except:
  338. numeric = default
  339. return numeric
  340. def insert_space_in_camelcase(self,value):
  341. """
  342. given a string, insert a space in from of upper case characters
  343. or numbers.
  344. Use to make a user presentable label
  345. :param value: the string to operate on
  346. :returns: the reformatted string
  347. """
  348. return re.sub('([A-Z]{1})', r' \1',value).strip().strip("_")
  349. def initiate_control_types(self):
  350. """
  351. initiate a dictionary of control type names with default values.
  352. :returns: dictionary of supported control types
  353. """
  354. control_types = dict()
  355. control_types["TextBox"] = "TextBox"
  356. control_types["MultiLineText"] = "MultiLineText"
  357. control_types["Dropdown"] = "Dropdown"
  358. control_types["Date"] = "Date"
  359. control_types["DateTime"] = "DateTime"
  360. control_types["NumericStepper"] = "NumericStepper"
  361. control_types["CheckBox"] = "CheckBox"
  362. control_types["Map"] = "Map"
  363. return control_types
  364. class AssessmentFormCreateRepresentation(object):
  365. """"
  366. A structure for defining table metadata and relationships between
  367. search profile names, id's and tables
  368. """
  369. def __init__(self,form_name=None,form_label=None,form_level=None,version=1,can_add_attachment=True,tab_label="Tab",layout_pattern="Single",widget_labels="Data",label_formatter=None):
  370. """
  371. AssessmentFormCreateRepresentation - a model defining the core form
  372. details - form, tab, layoutpattern, control group labels
  373. """
  374. self.fieldtypes = {
  375. "form_name": "str",
  376. "form_label": "str",
  377. "form_level": "str",
  378. "version": "int",
  379. "can_add_attachment": "bool",
  380. "tab_label":"string",
  381. "layout_pattern":"string",
  382. "widget_labels":"list[str]",
  383. "label_formatter": "string"
  384. }
  385. self._form_name = form_name
  386. self._form_label = form_label
  387. self._form_level = form_level
  388. self._version = version
  389. self._can_add_attachment = can_add_attachment
  390. self._tab_label = tab_label
  391. self._layout_pattern = layout_pattern
  392. if widget_labels == None:
  393. widget_labels = []
  394. self._widget_labels = widget_labels
  395. self._label_formatter = label_formatter
  396. @property
  397. def form_name(self):
  398. return self._form_name
  399. @form_name.setter
  400. def form_name(self,form_name):
  401. self._form_name = form_name
  402. @property
  403. def form_label(self):
  404. return self._form_label
  405. @form_label.setter
  406. def form_label(self,form_label):
  407. self._form_label = form_label
  408. @property
  409. def form_level(self):
  410. return self._form_level
  411. @form_level.setter
  412. def form_level(self,form_level):
  413. self._form_level = form_level
  414. @property
  415. def version(self):
  416. return self._version
  417. @version.setter
  418. def version(self,version):
  419. self._version = version
  420. @property
  421. def can_add_attachment(self):
  422. return self._can_add_attachment
  423. @can_add_attachment.setter
  424. def can_add_attachment(self,can_add_attachment):
  425. self._can_add_attachment = can_add_attachment
  426. @property
  427. def tab_label(self):
  428. return self._tab_label
  429. @tab_label.setter
  430. def tab_label(self,tab_label):
  431. self._tab_label = tab_label
  432. @property
  433. def layout_pattern(self):
  434. return self._layout_pattern
  435. @layout_pattern.setter
  436. def layout_pattern(self,layout_pattern):
  437. self._layout_pattern = layout_pattern
  438. @property
  439. def widget_labels(self):
  440. return self._widget_labels
  441. @widget_labels.setter
  442. def widget_labels(self,widget_labels):
  443. self._widget_labels = widget_labels
  444. @property
  445. def label_formatter(self):
  446. return self._label_formatter
  447. @label_formatter.setter
  448. def label_formatter(self,label_formatter):
  449. self._label_formatter = label_formatter
  450. def to_dict(self):
  451. """
  452. Returns the model properties as a dict
  453. """
  454. result = {}
  455. for attr, _ in six.iteritems(self.fieldtypes):
  456. value = getattr(self, attr)
  457. if isinstance(value, list):
  458. result[attr] = list(map(
  459. lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
  460. value
  461. ))
  462. elif hasattr(value, "to_dict"):
  463. result[attr] = value.to_dict()
  464. elif isinstance(value, dict):
  465. result[attr] = dict(map(
  466. lambda item: (item[0], item[1].to_dict())
  467. if hasattr(item[1], "to_dict") else item,
  468. value.items()
  469. ))
  470. else:
  471. result[attr] = value
  472. return result
  473. def to_str(self):
  474. """
  475. Returns the string representation of the model
  476. """
  477. return pformat(self.to_dict())
  478. def __repr__(self):
  479. """
  480. For `print` and `pprint`
  481. """
  482. return self.to_str()
  483. def __eq__(self, other):
  484. """
  485. Returns true if both objects are equal
  486. """
  487. return self.__dict__ == other.__dict__
  488. def __ne__(self, other):
  489. """
  490. Returns true if both objects are not equal
  491. """
  492. return not self == other
  493. if __name__ == "__main__":
  494. main()